package main

import (
	"log"
	"sync"
)

// 协程池状态常量
const (
	STOP = iota
	RUNNING
)

var GoWorkerPool = InitWorkerPool(10)

type TaskFunc func(videoPath string)

type Task struct {
	Func      TaskFunc
	VideoPath string
}

func (task *Task) Execute() {
	task.Func(task.VideoPath)
}

// WorkerPool 协程池
type WorkerPool struct {
	sync.Mutex
	Tasks    chan Task // 任务
	PoolSize int       // 协程池资源个数
	State    int       // 协程池状态
	Resource chan int  // 可用资源数
}

// InitWorkerPool 初始化协程池
func InitWorkerPool(poolSize int) *WorkerPool {
	pool := &WorkerPool{
		Tasks:    make(chan Task),
		PoolSize: poolSize,
		State:    STOP,
		Resource: make(chan int, poolSize),
	}

	// 写入可用资源数
	for i := 0; i < poolSize; i++ {
		pool.Resource <- 1
	}

	pool.Start()
	log.Println("协程池初始化完毕")
	return pool
}

func (pool *WorkerPool) Start() {
	pool.Lock()
	defer pool.Unlock()
	if pool.State == STOP {
		for i := 0; i < pool.PoolSize; i++ {
			go pool.worker()
		}
		pool.State = RUNNING
		log.Println("协程池协程启动成功")
	}
}

func (pool *WorkerPool) Stop() {
	pool.Lock()
	defer pool.Unlock()
	if pool.State == RUNNING {
		close(pool.Tasks)
		pool.State = STOP
	}
}

func (pool *WorkerPool) HasAvailableResource() bool {
	return len(pool.Resource) != 0
}

func (pool *WorkerPool) worker() {
	for {
		task, ok := <-pool.Tasks

		if !ok {
			return
		}

		select {
		case <-pool.Resource:
			log.Println("正在处理一条新的任务")
			task.Execute()
			pool.Resource <- 1
		default:
			pool.Tasks <- task
			log.Println("当前协程池无资源可用")
		}
	}
}
